#include "stdafx.h"
#include "EXSliderCtrl.h"

// CEXSliderCtrl

IMPLEMENT_DYNAMIC(CEXSliderCtrl, CSliderCtrl)

CEXSliderCtrl::CEXSliderCtrl()
{
	m_bSetBitmap = FALSE;

	m_nTopHeight = 0;
	m_nBottomHeight = 0;
	m_nLeftWidth = 0;
	m_nRightWidth = 0;
 
	m_nBkgndID = 0;
	m_nThumbID = 0;

	m_nNumOfBgPics = 0;
	m_crTransparent = RGB(255,0,255);
	m_crBkgnd = RGB(0, 255, 255);
	m_bFocus = FALSE;
	m_bSelect = FALSE;
}

CEXSliderCtrl::~CEXSliderCtrl()
{
}


BEGIN_MESSAGE_MAP(CEXSliderCtrl, CSliderCtrl)
	ON_WM_MOUSEMOVE()
	ON_WM_SIZE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_MESSAGE(WM_MOUSELEAVE, &CEXSliderCtrl::OnMouseLeaveNotify)
	ON_WM_MOUSEWHEEL()
END_MESSAGE_MAP()



// CEXSliderCtrl message handlers


void CEXSliderCtrl::SetResSet(CEXBaseResSet* pResSet)
{
  m_pSliderResSet = (CEXSliderCtrlResSet *)pResSet;
  if(m_pSliderResSet->m_nType == SLIDER_CTRL)
  {
    SetBkgndColor(m_pSliderResSet->m_crBkColor);
    SetBitmaps(m_pSliderResSet->m_arrImgId.GetAt(0), 
      m_pSliderResSet->m_arrImgId.GetAt(1), m_pSliderResSet->m_nImg_DivideCnt);
  }
}


LRESULT CEXSliderCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_PAINT && m_bSetBitmap)
	{
		CPaintDC dc(this);

		CRect rcThumb;
		GetThumbRect(rcThumb);

		CRect rcChannel;
		GetChannelRect(rcChannel);

		if (GetStyle() & TBS_VERT)
		{
			int nTop = rcChannel.top;
			int nBottom = rcChannel.bottom;
			rcChannel.top = rcChannel.left;
			rcChannel.bottom = rcChannel.right;
			rcChannel.left = nTop;
			rcChannel.right = nBottom;
		}

		CRect rcClient;
		GetClientRect(rcClient);

		CDC dcBkgnd;
		dcBkgnd.CreateCompatibleDC(&dc);

		CBitmap bmpBkgnd;
		bmpBkgnd.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());

		CBitmap * pOldBmpBkgnd = NULL;
		pOldBmpBkgnd = dcBkgnd.SelectObject(&bmpBkgnd);

		CDC dcImage;
		dcImage.CreateCompatibleDC(&dc);

		CBitmap * pOldBmpImage = NULL;
		pOldBmpImage = dcImage.SelectObject(&m_bmpChannelBkgnd);

		dcBkgnd.FillSolidRect(rcClient, m_crBkgnd);

		dcBkgnd.TransparentBlt(rcChannel.left, rcChannel.top, rcChannel.Width(), 
      rcChannel.Height(), &dcImage,	0, 0, rcChannel.Width(), 
      rcChannel.Height(), m_crTransparent);

		dcImage.SelectObject(pOldBmpImage);

		STATUS st;

		pOldBmpImage = dcImage.SelectObject(&m_bmpThumb);

		if (!IsWindowEnabled())
		{
			st = disable;
		}
		else if (m_bSelect)
		{
			st = select;
		}
		else if (m_bFocus)
		{
			st = focus;
		}
		else
		{
			st = normal;
		}

		dcBkgnd.TransparentBlt(rcThumb.left, rcThumb.top, rcThumb.Width(), 
      rcThumb.Height(), &dcImage,	rcThumb.Width()*st, 0, rcThumb.Width(), 
      rcThumb.Height(), m_crTransparent);

		dcImage.SelectObject(pOldBmpImage);

		dc.BitBlt(0,0,rcClient.Width(), rcClient.Height(), &dcBkgnd, 0, 0, SRCCOPY);
		dcBkgnd.SelectObject(pOldBmpBkgnd);

		return FALSE;		
	}

	return CSliderCtrl::WindowProc(message, wParam, lParam);
}

BOOL CEXSliderCtrl::SetBitmaps(UINT nBkgndID, UINT nThumbID, int nCount, 
                               int nTopHeight /* = 0*/, 
                               int nBottomHeight /* = 0*/, 
                               int nLeftWidth /* = 0*/, 
                               int nRightWidth /* = 0*/)
{
	m_nTopHeight = nTopHeight;
	m_nBottomHeight = nBottomHeight;
	m_nLeftWidth = nLeftWidth;
	m_nRightWidth = nRightWidth;

	m_nBkgndID = nBkgndID;
	m_nThumbID = nThumbID;
	m_nNumOfBgPics  = nCount;  

	CRect rcWnd;
	GetChannelRect(rcWnd);
	rcWnd.OffsetRect(-rcWnd.left, -rcWnd.top);

	CBitmap bmpTemp;
	if( !bmpTemp.LoadBitmap(m_nBkgndID) )
		return FALSE;

	if (GetStyle() & TBS_VERT)
	{
		int nTemp = rcWnd.right;
		rcWnd.right = rcWnd.bottom;
		rcWnd.bottom = nTemp;

		CDC * pDC = GetDC();

		CDC memDC; 
		memDC.CreateCompatibleDC(pDC);

		CDC srcDC;
		srcDC.CreateCompatibleDC(pDC);

		CBitmap* pOldBitmap1;
		pOldBitmap1 = srcDC.SelectObject(&bmpTemp);

		BITMAP bmpinfo;
		bmpTemp.GetBitmap(&bmpinfo);
		int bmpWidth = bmpinfo.bmWidth;
		int bmpHeight = bmpinfo.bmHeight;

		m_bmpChannelBkgnd.DeleteObject();

		CBitmap* pOldBitmap2;
		m_bmpChannelBkgnd.CreateCompatibleBitmap(pDC, rcWnd.Width(), rcWnd.Height());
		pOldBitmap2 = memDC.SelectObject(&m_bmpChannelBkgnd);

		memDC.FillSolidRect(rcWnd, m_crTransparent);

		// entireimage
		if (!memDC.TransparentBlt(0, 2, rcWnd.Width(), rcWnd.Height()-4,
			&srcDC,	0, 2, bmpWidth, bmpHeight-4, m_crTransparent))
			return FALSE;

		if (!memDC.TransparentBlt(0, 0, rcWnd.Width(), 2,
			&srcDC,	0, 0, bmpWidth, 2, m_crTransparent))
			return FALSE;

		if (!memDC.TransparentBlt(0, rcWnd.Height()-2, rcWnd.Width(), 2,
			&srcDC,	0, bmpHeight-2, bmpWidth, 2, m_crTransparent))
			return FALSE;

		srcDC.SelectObject(pOldBitmap1);
		memDC.SelectObject(pOldBitmap2);

		ReleaseDC(pDC);
		ReleaseDC(&srcDC);
		ReleaseDC(&memDC);
	}
	else
	{
		CDC * pDC = GetDC();

		CDC memDC; 
		memDC.CreateCompatibleDC(pDC);

		CDC srcDC;
		srcDC.CreateCompatibleDC(pDC);

		CBitmap* pOldBitmap1;
		pOldBitmap1 = srcDC.SelectObject(&bmpTemp);

		BITMAP bmpinfo;
		bmpTemp.GetBitmap(&bmpinfo);
		int bmpWidth = bmpinfo.bmWidth;
		int bmpHeight = bmpinfo.bmHeight;

		m_bmpChannelBkgnd.DeleteObject();

		CBitmap* pOldBitmap2;
		m_bmpChannelBkgnd.CreateCompatibleBitmap(pDC,rcWnd.Width(),rcWnd.Height());
		pOldBitmap2 = memDC.SelectObject(&m_bmpChannelBkgnd);

		memDC.FillSolidRect(rcWnd, m_crTransparent);

		// entireimage
		if (!memDC.TransparentBlt(2, 0, rcWnd.Width()-4, rcWnd.Height(),
			&srcDC,	2, 0, bmpWidth-4, bmpHeight, m_crTransparent))
			return FALSE;

		if (!memDC.TransparentBlt(0, 0, 2, rcWnd.Height(),
			&srcDC,	0, 0, 2, bmpHeight, m_crTransparent))
			return FALSE;

		if (!memDC.TransparentBlt(rcWnd.Width()-2, 0, 2, rcWnd.Height(),
			&srcDC,	bmpWidth-2, 0, 2, bmpHeight, m_crTransparent))
			return FALSE;

		srcDC.SelectObject(pOldBitmap1);
		memDC.SelectObject(pOldBitmap2);

		ReleaseDC(pDC);
		ReleaseDC(&srcDC);
		ReleaseDC(&memDC);
	}

	GetThumbRect(rcWnd);
	rcWnd.OffsetRect(-rcWnd.left, -rcWnd.top);

	bmpTemp.DeleteObject();
	if( !bmpTemp.LoadBitmap(m_nThumbID) )
		return FALSE;

	m_bmpThumb.DeleteObject();

	if( !InitBgBitmap(rcWnd, bmpTemp, m_bmpThumb, normal, m_nNumOfBgPics,
		nTopHeight, nBottomHeight, nLeftWidth, nRightWidth) ) 
		return FALSE;

	if( !InitBgBitmap(rcWnd, bmpTemp, m_bmpThumb, focus, m_nNumOfBgPics,
		nTopHeight, nBottomHeight, nLeftWidth, nRightWidth) )
		return FALSE;

	if( !InitBgBitmap(rcWnd, bmpTemp, m_bmpThumb, select, m_nNumOfBgPics,
		nTopHeight, nBottomHeight, nLeftWidth, nRightWidth) )
		return FALSE;

	if( !InitBgBitmap(rcWnd, bmpTemp, m_bmpThumb, disable, m_nNumOfBgPics,
		nTopHeight, nBottomHeight, nLeftWidth, nRightWidth) )
		return FALSE;

	m_bSetBitmap = TRUE;

	return TRUE;
}

BOOL CEXSliderCtrl::InitBgBitmap(CRect & rcWnd, CBitmap & src, CBitmap & dist,
                                 int index, int count, int nTopHeight, 
                                 int nBottomHeight, int nLeftWidth, 
                                 int nRightWidth)
{
	CDC * pDC = GetDC();

	CDC memDC; 
	memDC.CreateCompatibleDC(pDC);

	CDC srcDC;
	srcDC.CreateCompatibleDC(pDC);

	CBitmap* pOldBitmap1;
	pOldBitmap1 = srcDC.SelectObject(&src);

	BITMAP bmpinfo;
	src.GetBitmap(&bmpinfo);
	int bmpWidth = bmpinfo.bmWidth / count;
	int bmpHeight = bmpinfo.bmHeight;
	int orix = bmpWidth * (index < count ? index : 0);

	if (!dist.GetSafeHandle())
		dist.CreateCompatibleBitmap(pDC, rcWnd.Width()*count, rcWnd.Height());

	CBitmap bmpTemp;
	bmpTemp.CreateCompatibleBitmap(pDC, rcWnd.Width(), rcWnd.Height());

	CBitmap* pOldBitmap2;
	pOldBitmap2 = memDC.SelectObject(&bmpTemp);

	memDC.FillSolidRect(rcWnd, m_crTransparent);

  if(!m_nBottomHeight && !m_nLeftWidth && !m_nRightWidth && !m_nTopHeight)
    memDC.StretchBlt(0, 0, rcWnd.Width(), rcWnd.Height() , &srcDC,
                    orix, 0, bmpWidth, bmpHeight, SRCCOPY);

  else
  {
	  // entireimage
  	memDC.TransparentBlt(nLeftWidth,
		nTopHeight,
		rcWnd.Width()  - ( nLeftWidth + nRightWidth ) ,
		rcWnd.Height() -  ( nTopHeight + nBottomHeight) ,
		&srcDC,
		orix + nLeftWidth,
		nTopHeight,
		bmpWidth - ( nLeftWidth + nRightWidth ) ,
		bmpHeight - ( nTopHeight + nBottomHeight ) , m_crTransparent);

	  // topbar
	  memDC.TransparentBlt(nLeftWidth, 0, rcWnd.Width() - (nLeftWidth + 
      nRightWidth), nTopHeight, &srcDC,orix + nLeftWidth, 0, bmpWidth - 
      ( nLeftWidth + nRightWidth) , nTopHeight, m_crTransparent);

	  // bottombar
	  memDC.TransparentBlt(nLeftWidth, rcWnd.bottom - nBottomHeight, 
      rcWnd.Width() - ( nLeftWidth + nRightWidth), nBottomHeight,
		  &srcDC,orix + nLeftWidth,bmpHeight - nBottomHeight,bmpWidth - 
      ( nLeftWidth + nRightWidth) , nBottomHeight, m_crTransparent );

	  // sidebar
	  memDC.TransparentBlt(0, nTopHeight, nLeftWidth, rcWnd.bottom - nTopHeight - 
      nBottomHeight , &srcDC, orix, nTopHeight, nLeftWidth, bmpHeight - 
      ( nTopHeight + nBottomHeight ) , m_crTransparent);

	  memDC.TransparentBlt(rcWnd.right - nRightWidth , nTopHeight, nRightWidth, 
      rcWnd.bottom - nTopHeight - nBottomHeight , &srcDC, orix +  bmpWidth - 
      nRightWidth, nTopHeight, nRightWidth, bmpHeight - 
      nTopHeight - nBottomHeight , m_crTransparent);

	  // lefttop,leftbottom,righttop,rightbottom
	  if( !memDC.BitBlt(0, 0, nLeftWidth, nTopHeight, &srcDC, orix, 0, SRCCOPY) )
		  return FALSE;

	  if( !memDC.BitBlt(0, rcWnd.bottom - nBottomHeight, nLeftWidth, nBottomHeight, 
		  &srcDC,orix,bmpHeight - nBottomHeight, SRCCOPY) )
		  return FALSE;

	  if( !memDC.BitBlt(rcWnd.right - nRightWidth, 0, nRightWidth, nTopHeight, 
		  &srcDC,orix + bmpWidth - nRightWidth, 0, SRCCOPY) )
		  return FALSE;

	  if( !memDC.BitBlt(rcWnd.right - nRightWidth, rcWnd.bottom - nBottomHeight, 
      nRightWidth, nBottomHeight, &srcDC,orix + bmpWidth - nRightWidth, 
      bmpHeight - nBottomHeight, SRCCOPY) )
		  return FALSE;
  }

	CDC dcThumb;
	dcThumb.CreateCompatibleDC(pDC);

	CBitmap * pOldBitmap3 = dcThumb.SelectObject(&dist);

	dcThumb.BitBlt(rcWnd.Width()*index, 0, rcWnd.Width(), rcWnd.Height(), 
    &memDC, 0, 0, SRCCOPY);

	srcDC.SelectObject(pOldBitmap1);
	memDC.SelectObject(pOldBitmap2);
	dcThumb.SelectObject(pOldBitmap3);

	ReleaseDC(pDC);
	ReleaseDC(&srcDC);
	ReleaseDC(&memDC);

	return TRUE;
}

void CEXSliderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
	TRACKMOUSEEVENT tme = {0};
	tme.cbSize = sizeof tme;
	tme.dwFlags = TME_LEAVE;
	tme.dwHoverTime = 10;
	tme.hwndTrack = GetSafeHwnd();

	TrackMouseEvent(&tme);

	CRect rcThumb;
	GetThumbRect(rcThumb);

	m_bFocus = FALSE;

	if (rcThumb.PtInRect(point))
	{
		m_bFocus = TRUE;
	}

	Invalidate(FALSE);

	CSliderCtrl::OnMouseMove(nFlags, point);
}

void CEXSliderCtrl::OnSize(UINT nType, int cx, int cy)
{
	CSliderCtrl::OnSize(nType, cx, cy);

	if (IsWindow(GetSafeHwnd()) && m_bSetBitmap)
	{
		SetBitmaps(m_nBkgndID, m_nThumbID, m_nNumOfBgPics, m_nTopHeight, 
      m_nBottomHeight, m_nLeftWidth, m_nRightWidth);
	}
}

void CEXSliderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
	CRect rcThumb;
	GetThumbRect(rcThumb);

	if (rcThumb.PtInRect(point))
	{
		m_bSelect = TRUE;
	}
	Invalidate(FALSE);

	CSliderCtrl::OnLButtonDown(nFlags, point);
}

void CEXSliderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
	m_bSelect = FALSE;
	Invalidate(FALSE);

	CSliderCtrl::OnLButtonUp(nFlags, point);
}

LRESULT CEXSliderCtrl::OnMouseLeaveNotify(WPARAM w, LPARAM l)
{
	m_bFocus = FALSE;
	Invalidate(FALSE);

	return 0;
}

void CEXSliderCtrl::SetBkgndColor(COLORREF crBkgnd)
{
	m_crBkgnd = crBkgnd;
	Invalidate(FALSE);
}

BOOL CEXSliderCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	int nCount = zDelta / 120;

	WORD nDirection = SB_LINEUP;
	WORD nPos = GetPos();

	if (nCount < 0)
	{
		nDirection = SB_LINEDOWN;
		nCount = -nCount;
	}

	for (int i=0; i<nCount; i++)
	{
		GetParent()->PostMessage(WM_HSCROLL, MAKEWPARAM(nDirection, nPos), (LPARAM)GetSafeHwnd());
	}

	return CSliderCtrl::OnMouseWheel(nFlags, zDelta, pt);
}
